import { StatusBar } from "expo-status-bar";
import {
    StyleSheet,
    View,
    Pressable,
    Text,
    StatusBar as RNStatusBar,
    TouchableOpacity,
    Image as RNImage,
    TextInput,
    KeyboardTypeOptions,
    ActivityIndicator,
} from "react-native";
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
import { Image as Expo_Image, ImageProps } from 'expo-image'
import Entypo from '@expo/vector-icons/Entypo';
import AntDesign from '@expo/vector-icons/AntDesign';
import DatePicker from '@react-native-community/datetimepicker'
import { useActionSheet } from '@expo/react-native-action-sheet';

import { CColor, CFlex, CStyle } from "../constant/css";
import util from "../common/utils/util";
import { useSetState } from "../common/hooks";
import CommonServer from "../common/service/CommonServer";

/**
 * * expo-image 更强大的图片组件
 * @param {ImageProps} props
 */
export const ExpoImage = (props) => <Expo_Image {...props} />

/**
 * * 公共按钮
 * ?       const label = '查看房源详情'
 * ?       <FORM.Button
 * ?           label={label}
 * ?           style={{ marginVertical: 10 }}
 * ?           onClick={() => {}}
 * ?       />
 *
 * @param {object} props 配置项
 * @param {string} props.label 内容
 * @param {number} [props.activeOpacity] 反馈
 * @param {Function} [props.onClick] 响应事件
 * @param {StyleProp<ViewStyle>} [props.style] 容器样式
 * @param {StyleProp<ViewStyle>} [props.buttonStyle] 容器样式 旧属性
 * @param {StyleProp<ViewStyle>} [props.textStyle] 文字样式
 * @param {StyleProp<ViewStyle>} [props.fontStyle] 文字样式 旧属性
 * @param {React.ReactElement} [props.children] 自定义组件
 * @returns {React.ReactElement}
 */
export const Button = (props) => {
    const {
        label = '', onClick = '', children = '', activeOpacity = 0.8,
        style = {}, textStyle = {}, isLoading = false,
    } = props || {}
    return (
        <>
            <TouchableOpacity style={{ ...CStyle.button, ...style }} activeOpacity={activeOpacity} onPress={() => onClick?.()}>
                {!!children && children}
                {isLoading && <ActivityIndicator size={23} color={CColor.White} />}
                {!isLoading && <Text style={{ color: '#fff', letterSpacing: 5, fontSize: 16, ...textStyle }}>{label}</Text>}
            </TouchableOpacity>
        </>
    )
}

/**
 * * Label
 * @param {object} props
 * @param {string} props.title 标题
 * @param {boolean} [props.required] 必填项
 * @param {boolean} [props.showRequired] 占位
 * @param {StyleProp<ViewStyle>} [props.style] 文字样式
 * @returns {React.ReactElement}
 */
export const Label = ({ showRequired = true, required = false, title = '', style = {} }) =>
    <View style={styles.labelContainer}>
        <Text style={[styles.labelText, { ...style }]}>
            {showRequired ? <Text style={{ color: CColor.Red }}>{required ? '*' : ' '}</Text> : ''}
            {title}
        </Text>
    </View>

/**
 * * 输入框
 * @param {object} props 配置项
 * @param {string} props.title 标题
 * @param {boolean} [props.required] 必填项
 * @param {any} props.data 数据源
 * @param {string} props.key 键值
 * @param {Function} [props.onClick] 事件
 * @param {Function} [props.unit] 单位组件
 * @param {string} [props.placeholder] 提示文字
 * @param {string} [props.placeholderTextColor] 提示文字颜色
 * @param {'left' | 'center' | 'right' | undefined} [props.textAlign] 对齐
 * @param {string} [props.returnKeyType] 下一步按键类型
 * @param {KeyboardTypeOptions} [props.keyboardType] 键盘类型
 * @returns {React.ReactElement}
 */
export const FormInput = (props) => {
    const {
        title = '', required = false,
        data = {}, key = '', onClick = null, unit = null,
        placeholder = '', placeholderTextColor = '', selectionColor = '#c0c4cc',
        textAlign = '', returnKeyType = '', keyboardType = '',
    } = props
    return (
        <View style={[styles.formRow, styles.formContainer, styles.formSplit]}>
            <Label title={title} required={required} />
            <View style={{ flex: 1, paddingLeft: 10, paddingRight: 10 }}>
                <TextInput
                    onChangeText={newText => onClick?.(newText)}
                    value={data[key] || ''}
                    placeholder={placeholder || `请输入${title}`}
                    placeholderTextColor={placeholderTextColor}
                    selectionColor={selectionColor}
                    textAlign={textAlign}
                    returnKeyType={returnKeyType}
                    keyboardType={keyboardType}
                />
            </View>
            {unit ? unit() : null}
        </View>
    )
}

/**
 * * 图片上传
 * @param {object} props 配置项
 * @param {string} props.title 标题
 * @param {boolean} [props.required] 必填项
 * @param {any[]} [props.data] 数据源
 * @param {string} [props.key] key
 * @param {'IMAGE'} [props.type] type 表单标识
 * @param {<T extend {url:string,canDelete:boolean}>[]} [props.urls] 展示的图片数组
 * @param {Function} [props.onClick] 图片点击
 * @param {boolean} [props.showAdd] 添加按钮
 * @param {number} [props.max] 最大数
 * @param {string} [props.addTitle] 按钮名称
 * @param {Function} [props.addFun] 添加事件
 * @param {boolean} [props.showAdd] 删除按钮
 * @param {boolean} [props.showDelete] 删除按钮
 * @param {Function} [props.deleteFun] 添加事件
 * @returns {React.ReactElement}
 */
export const FormImage = (props) => {
    const {
        title = '', required = false,
        type = '', data = {}, key = '', // 表单
        urls = [], onClick = null,
        showAdd = false, max = 1, addTitle = '添加图片', addFun = null,
        showDelete = false, deleteFun = null,
    } = props
    const [state, setState] = useSetState({
        isUpload: false,
        hash: '',
    })
    const tempDataKey = max === 1 ? (data[key] ? [data[key]] : []) : data[key]
    const urlArr = type === FORM_TYPE.IMAGE ? tempDataKey : urls
    const imgStyle = max === 1 ? styles.onePickImage : styles.pickImage


    const uploadImage = async () => {
        const [base64Err, base64] = await util.pickImage({ allowsEditing: false })
        if (base64Err) {
            return base64Err.message && util.showInfo(base64Err)
        }
        if (state.isUpload) return
        setState({ isUpload: true })
        const { base64: str } = base64 || {}
        const [err, res] = await CommonServer.uploadImage({ base64: str })
        setState({ isUpload: false, hash: res?.data?.hash })
        if (err) return util.showInfo(err)
        addFun?.(res?.data || {})
    }

    const deleteImage = async (item) => {
        const hash = item.hash
        hash && CommonServer.deleteImage({ hash })
        deleteFun?.(item)
    }

    const renderImage = () =>
        urlArr.map(item =>
            <Pressable key={item.url} style={styles.pickImageContainer} onPress={() => onClick?.(item)}>
                <ExpoImage
                    contentFit='contain'
                    style={imgStyle}
                    source={{ uri: item.url }}
                />
                {item.canDelete ?
                    <Pressable style={styles.deleteImage} onPress={() => deleteImage(item)}>
                        <MaterialCommunityIcons name="delete-circle" size={24} color={CColor.Red} />
                    </Pressable> : null}
            </Pressable>
        )

    const renderButton = () =>
        showAdd && urlArr.length < max ?
            <Pressable style={[styles.pickImageContainer, { borderColor: CColor.Blue }]} onPress={uploadImage}>
                <View style={[imgStyle, CFlex.cc]}>
                    {state.isUpload ?
                        <ActivityIndicator size="large" color={CColor.Blue} /> :
                        <>
                            <Entypo name="images" size={48} color={CColor.Blue} />
                            <View style={{ height: 10 }} />
                            <Text style={[{ color: CColor.Blue, fontSize: 10 }]}>{addTitle}</Text>
                        </>
                    }
                </View>
            </Pressable> : null

    return (
        <View style={[styles.formContainer, styles.formSplit]}>
            <Label title={title} required={required} />
            <View style={[CFlex.row, CFlex.ss, CFlex.wrap, { marginTop: 15 }]}>
                {renderImage()}
                {renderButton()}
            </View>
        </View>
    )
}

/**
 * * 表单 单选
 * @param {object} props 配置项
 * @param {string} props.title 标题
 * @param {boolean} props.required 必填
 * @param {any} props.data 源数据
 * @param {string} props.key key
 * @param {string[]|number[]} props.singleData 候选项
 * @param {Function} props.onClick 点击事件
 * @returns {React.ReactElement}
 */
export const FormSingle = (props) => {
    const {
        title = '', required = false,
        data = {}, key = '',
        singleData = [], singleKey = '', onClick = null
    } = props

    const valueStyle = data?.[key] ? styles.labelValueBlack : styles.labelValue
    const titleStr = `请选择${title}`
    return (
        <View style={[styles.formRow, styles.formContainer, styles.formSplit]}>
            <Label title={title} required={required} />
            <ActionSheet
                title={titleStr}
                singleData={singleData}
                singleKey={singleKey}
                onClick={onClick}
            >
                <View style={[CFlex.row, CFlex.ec]}>
                    <Text style={[valueStyle, { textAlign: 'right' }]}>{data?.[key] || titleStr}</Text>
                    <Entypo name="chevron-small-right" size={20} color={valueStyle.color} />
                </View>
            </ActionSheet>
        </View>
    )
}

export const FormMultiple = (props) => {
    return null
}

/**
 * * 时间 选择
 * @param {object} props 配置项
 * @param {string} props.title 标题
 * @param {boolean} props.required 必填
 * @param {any} props.data 源数据
 * @param {string} props.key key
 * @param {Function} props.onClick 点击事件
 * @returns {React.ReactElement}
 */
export const FormDate = (props) => {
    const {
        title = '', required = false,
        data = {}, key = '',
        onClick = null
    } = props
    const [state, setState] = useSetState({
        showCalender: false
    })
    const valueStyle = data?.[key] ? styles.labelValueBlack : styles.labelValue
    const titleStr = data?.[key] || `请选择${title}`
    const onChange = (val) => {
        setState({ showCalender: false })
        const { timestamp } = val.nativeEvent
        onClick(util.dayjs(timestamp).format('YYYY-MM-DD HH:mm'))
    }

    return (
        <View style={[styles.formRow, styles.formContainer, styles.formSplit]}>
            <Label title={title} required={required} />
            <Pressable style={[CFlex.row, CFlex.ec]} onPress={() => setState({ showCalender: true })}>
                <Text style={[valueStyle, { textAlign: 'right' }]}>{util.dayjs(titleStr).format('YYYY-MM-DD HH:mm')}</Text>
                <Entypo name="chevron-small-right" size={20} color={valueStyle.color} />
            </Pressable>
            {state.showCalender ?
                <DatePicker
                    testID={`${title}-${key}`}
                    value={util.dayjs(data?.[key]).toDate()}
                    mode='date'
                    is24Hour={true}
                    display="calendar"
                    onChange={onChange}
                /> : null}
        </View>
    )
}

/**
 * * 配置表单
 * @param {object} props
 * @param {any[]} props.list 表单数组
 * @param {object} props.data 表单数组
 */
export const FormList = (props) => {
    const obj = {
        [FORM_TYPE.INPUT]: FormInput,
        [FORM_TYPE.IMAGE]: FormImage,
        [FORM_TYPE.SINGLE]: FormSingle,
        [FORM_TYPE.MULTIPLE]: FormMultiple,
        [FORM_TYPE.DATE]: FormDate,
        [FORM_TYPE.OTHER]: (item) => item?.selfComponent?.(),
    }
    return (
        <View>
            {props?.list?.map(item => {
                item.data = props.data || {}
                return <View key={item.key}>{obj[item.type]?.(item)}</View>
            })}
        </View>
    )
}

// * 表单枚举
export const FORM_TYPE = {
    INPUT: 'INPUT',
    IMAGE: 'IMAGE',
    SINGLE: 'SINGLE',
    MULTIPLE: 'MULTIPLE',
    DATE: 'DATE',
    OTHER: 'OTHER',
}

/**
 * * 单选组件
 * @param {object} props 配置项
 * @param {React.Component} props.children 自定义视图
 * @param {any[]} props.singleData 数据
 * @param {string} props.singleKey 元素为对象时，指定 key 值用于展示
 * @param {Function} props.onClick 事件
 * @returns {React.ReactElement}
 */
export const ActionSheet = (props) => {
    const { showActionSheetWithOptions } = useActionSheet();
    const showActionSheet = () => {
        const { title = '', singleData = [], singleKey = '', onClick = null } = props
        const isObject = singleData.every(_ => _ && _ instanceof Object)
        let options = []
        if (isObject) {
            options = util.getArrayByKey(singleData, singleKey)
        } else {
            options = singleData.reduce((sum, current) => sum.push(`${current}`) && sum, []);
        }
        options.push('取消')
        const cancelButtonIndex = options.length - 1
        const containerStyle = {
            borderRadius: 20,
            marginBottom: 10,
            marginHorizontal: 10,
            ...CFlex.cc,
        }
        const titleTextStyle = {
            color: CColor.Black,
        }
        const textStyle = {
            color: CColor.DeepGray,
            width: '100%',
            textAlign: 'center',
        }
        const config = {
            containerStyle,
            title,
            titleTextStyle,
            textStyle,
            options,
            cancelButtonIndex,
            showSeparators: true,
        }
        if (options.length > 6) {
            containerStyle.height = 400
            // 设置为 true 启用滚动
            config.scrollEnabled = true
            // config.useModal = true
        }
        showActionSheetWithOptions(
            config,
            (buttonIndex) => {
                if (buttonIndex !== cancelButtonIndex) {
                    onClick?.(buttonIndex, options[buttonIndex], singleData[buttonIndex], singleData)
                }
            }
        );
    };

    return (
        <Pressable style={{ flex: 1 }} onPress={showActionSheet}>
            {props.children}
        </Pressable>
    );
}

/**
 * * 表单渲染 快速渲染
 *
 * ?     const form_list = [
 * ?         {"label": "卧室：", "valueFunc": [Function valueFunc]}, // valueFunc 自定义展示值函数
 * ?         {"labelFunc": [Function valueFunc], "value": "key1"}, // labelFunc 自定义标题函数
 * ?         {"label": "挂画：", "value":"key2"}, // value 数据源 key
 * ?         {"label": "床：", "valueFunc": [Function valueFunc], "line": true}, // line 单独一行
 * ?     ]
 * ?     const data = {} // 数据源
 * ?     <FORM.FormItem
 * ?         labelStyle={{ fontSize: 16 }}
 * ?         list={form_list}
 * ?         data={data}
 * ?     />
 *
 * @param {Array<object>} list 数组对象
 * @param {object} data 源数据
 * @param {string} list.label 名称
 * @param {Function} list.labelFunc 名称展示自定义方法
 * @param {string} list.value 名称
 * @param {string} list.unit 单位
 * @param {Function} list.valueFunc 值更新自定义方法
 * @param {boolean} list.line 单行展示
 * @param {StyleProp<ViewStyle>} labelStyle label 样式
 * @returns {JSX.Element}
 */
export const FormItem = (props) => {
    const { list = [], data = {}, labelStyle = {} } = props || {}
    return (
        <View style={[CFlex.row, CFlex.wrap]}>
            {
                list.map(item =>
                    <View key={item.value} style={[{ paddingVertical: 6, width: item?.line ? '100%' : '50%' }, CFlex.row, CFlex.sc]}>
                        {item.labelComponent ?
                            item.labelComponent()
                            :
                            <Text style={{ color: '#b3b3b3', fontSize: 14, ...labelStyle }}>
                                {item.labelFunc ? item.labelFunc(data) : item.label}
                            </Text>
                        }
                        {item.valueComponent ?
                            item.valueComponent() :
                            <TouchableOpacity activeOpacity={1} style={[CFlex.row, CFlex.sc]} onPress={() => {
                                item.onClick?.(item)
                            }}>
                                {(item.value || item.valueFunc) && (
                                    <Text numberOfLines={1}
                                        style={{
                                            color: '#333333', fontSize: 14, ...labelStyle,
                                            ...(item?.textStyle || {})
                                        }}>
                                        {item.valueFunc ? item.valueFunc(data) : (data?.[item.value] || '--') + (data?.[item.value] && item.unit ? item.unit : '')}
                                    </Text>
                                )}
                                {item.onClick && <AntDesign name="right" size={24} color="black" />}
                            </TouchableOpacity>
                        }
                    </View>
                )
            }
        </View >
    )
}

const styles = StyleSheet.create({
    labelContainer: {
        width: 100,
    },
    labelText: {
        color: CColor.Black,
        fontSize: 15,
    },
    labelValue: {
        color: '#c7c7c7',
        fontSize: 14,
    },
    labelValueBlack: {
        color: CColor.Black,
        fontSize: 14,
    },
    formRow: {
        ...CFlex.row,
        ...CFlex.sb,
    },
    formContainer: {
        width: '100%',
        paddingVertical: 13,
        paddingHorizontal: 15,
    },
    formSplit: {
        borderBottomWidth: 1,
        borderColor: CColor.Gray,
    },
    pickImageContainer: {
        margin: 3,
        padding: 3,
        borderRadius: 10,
        borderWidth: 1,
        borderColor: CColor.Gray,
    },
    pickImage: {
        width: 150,
        height: 150,
        borderRadius: 10,
    },
    onePickImage: {
        width: 300,
        height: 200,
        borderRadius: 10,
    },
    deleteImage: {
        position: 'absolute',
        right: 0,
        top: 0,
    }
})